
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>项目中缓存的设计 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>项目中缓存的设计 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">策略</div>
          <div class="card-question">在选择缓存策略时，除了数据访问和更新频率，还需要考虑哪些核心因素？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">策略</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">除了数据访问和更新频率，还需要考虑数据的时效性和系统资源情况。时效性决定了缓存更新的速度，而系统资源情况（如内存容量、存储成本、网络带宽）则影响缓存类型的选择，例如高频访问的数据适合放入内存缓存，而冷数据可考虑外部存储缓存。</div>
          </div>
          <div class="card-source">来源: 缓存策略选择 -> 1. 缓存策略的核心影响因素</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">LRU (最近最少使用) 和 LFU (最不经常使用) 这两种缓存淘汰策略的主要区别和适用场景是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">LRU (Least Recently Used) 策略优先淘汰最近最少使用的数据，适合数据访问有较强时间局部性的场景，如用户个人主页。而 LFU (Least Frequently Used) 策略则根据访问频次淘汰访问次数最少的数据，适合访问频率较为稳定的系统，如新闻系统的热门新闻缓存。</div>
          </div>
          <div class="card-source">来源: 缓存策略选择 -> 2. 常见的缓存策略</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">策略</div>
          <div class="card-question">什么是“主动失效”缓存策略？它与“被动失效”策略相比，优缺点分别是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">策略</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">“主动失效”是指当数据源更新或删除时，系统主动将相关缓存数据清除。其优点是能有效避免缓存脏数据，提高数据一致性；缺点是需要额外的实现逻辑和通知机制，复杂度较高。相比之下，“被动失效”是在请求缓存数据时才检查其是否过期，优点是节省资源、减少更新次数，缺点是命中失效数据时会增加请求延迟。</div>
          </div>
          <div class="card-source">来源: 缓存失效策略 -> 2. 主动失效（Active Expiration） & 3. 被动失效（Lazy Expiration）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">防护</div>
          <div class="card-question">如何区分缓存雪崩和缓存击穿？请简述它们各自的核心防护策略。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">防护</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">缓存雪崩是指大量缓存数据在短时间内同时失效，导致请求全部涌向数据库。其核心防护策略包括分散缓存过期时间（如设置随机TTL）、限流降级或设计多级缓存。缓存击穿是指单个热点数据失效，导致大量并发请求同时访问数据库。其核心防护策略包括使用互斥锁或分布式锁，以及对热点数据采用“永不过期”的逻辑过期方案。</div>
          </div>
          <div class="card-source">来源: 缓存穿透、雪崩、击穿防护 -> 2. 缓存雪崩及防护措施 & 3. 缓存击穿及防护措施</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">防护</div>
          <div class="card-question">什么是缓存穿透？文档中提到了哪两种主要的防护措施？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">防护</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">缓存穿透是指对数据库中不存在的数据进行请求，导致请求每次都穿透缓存直接访问数据库。文档中提到的主要防护措施有两种：1. 使用布隆过滤器（Bloom Filter）在缓存前拦截对不存在数据的请求；2. 采用空值缓存策略，即将不存在的数据也缓存起来，但通常设置一个较短的过期时间（TTL）。</div>
          </div>
          <div class="card-source">来源: 缓存穿透、雪崩、击穿防护 -> 1. 缓存穿透及防护措施</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">在处理缓存一致性时，“先更新数据库再失效缓存”和“先失效缓存再更新数据库”这两种模式各有什么潜在风险？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">“先更新数据库再失效缓存”的潜在风险是，在失效操作完成前，其他请求可能会读取到旧的缓存数据，造成短暂的数据不一致。而“先失效缓存再更新数据库”的潜在风险是，在高并发下，一个请求失效缓存后，另一个请求可能在数据库更新前将旧数据读出并写回缓存，引发数据不一致，也可能导致缓存穿透。</div>
          </div>
          <div class="card-source">来源: 缓存并发处理 -> 5. 缓存失效模式</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">缓存一致性可以分为哪三种类型？它们之间有何区别？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">缓存一致性分为三种类型：1. 强一致性：要求每次更新数据库时，缓存和数据库必须完全同步，性能代价大。2. 最终一致性：允许缓存与数据库在短时间内不一致，但在一段时间后会达到一致，适用于大多数场景。3. 弱一致性：允许缓存与数据库不一致且不保证何时一致，适用于实时性要求低的业务场景。</div>
          </div>
          <div class="card-source">来源: 缓存并发处理 -> 1. 缓存一致性的分类</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">Redis 提供了哪两种持久化机制？它们的核心区别和适用场景是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Redis 提供了 RDB (快照) 和 AOF (日志) 两种持久化机制。RDB 是在指定时间间隔内创建数据快照，优点是恢复速度快、文件小，但可能丢失最近的数据，适用于数据更新频率较低的场景。AOF 是记录每条写操作到日志文件，优点是数据一致性高、不易丢失数据，但文件较大、恢复稍慢，适用于对数据一致性要求高的场景。</div>
          </div>
          <div class="card-source">来源: 缓存选择与持久化 -> 2. 缓存持久化策略</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">监控</div>
          <div class="card-question">在进行缓存监控时，除了缓存命中率，还有哪些关键指标需要关注？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">监控</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">除了缓存命中率和失效率，还需要关注三个关键指标：1. 请求量监控，特别是高峰流量和热点数据检测；2. 错误与超时监控，如缓存服务器的请求超时率和连接失败等错误率；3. 缓存容量监控，包括内存使用情况和数据TTL状态，以防因容量问题导致缓存驱逐或雪崩。</div>
          </div>
          <div class="card-source">来源: 缓存监控与优化 -> 1. 缓存监控</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">什么是二级缓存（Multi-Level Caching）？它主要适用于什么场景，并有什么优缺点？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">二级缓存是将缓存分为多级，例如本地缓存（一级）和分布式缓存（二级）。它主要适用于大规模分布式系统，在高并发和多层架构下确保低延迟访问。其优点是有效降低了系统的网络延迟；缺点是引入了多层级同步机制，增加了数据一致性维护的复杂性。</div>
          </div>
          <div class="card-source">来源: 缓存策略选择 -> 2. 常见的缓存策略</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">策略</div>
          <div class="card-question">文档中提到的“延迟双删策略”是如何工作的，它主要解决了什么问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">策略</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">“延迟双删策略”的工作流程是：先删除缓存，再更新数据库，然后在一段延迟时间后再次删除缓存。它主要解决了在“先失效缓存再更新数据库”模式下，因高并发读写冲突导致旧数据被重新写入缓存的数据不一致问题。</div>
          </div>
          <div class="card-source">来源: 缓存并发处理 -> 5. 缓存失效模式</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在选择分布式缓存系统时，Redis 和 Memcached 的主要区别体现在哪些方面？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">主要区别体现在三个方面：1. 数据结构支持：Redis支持字符串、哈希、列表等多种复杂数据结构，而Memcached主要是简单的Key-Value结构。2. 持久化能力：Redis提供RDB和AOF两种持久化机制，而Memcached没有持久化功能。3. 性能和功能：两者性能都很好，但Redis功能更丰富，而Memcached以其简单和极高的性能著称，适合纯粹的KV缓存场景。</div>
          </div>
          <div class="card-source">来源: 缓存选择与持久化 -> 1. 缓存系统的选择</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
